<template>
    <div class="boxs">
        <div class="maskLoading" v-if="isLoading">
            <div class="loading">
                <div :style="{ width: loadingWidth + '%' }"></div>
            </div>
            <div style="padding-left: 10px">{{ parseInt(loadingWidth) }}%</div>
        </div>
        <div class="mask">
            <p>x : {{ x }} y:{{ y }} z :{{ z }}</p>
            <button @click="isAutoFun">转动车</button>
            <button @click="stop">停止</button>
            <!-- <div class="flex">
        <div @click="setCarColor(index)" v-for="(item, index) in colorAry" :style="{ backgroundColor: item }"
          :key="index"></div>
      </div> -->
        </div>
    </div>
</template>

<script setup>
import { onMounted, reactive, ref, toRefs } from "vue";
import * as THREE from 'three'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
// import { OBJLoader } from "../../public/static/js/OBJLoader";
import { GUI } from 'dat.gui';
const gui = new GUI();


const loader = new OBJLoader();
const defaultMap = {
    x: 0,
    y: 1,
    z: 10,
}; // 相机的默认坐标
const map = reactive(defaultMap); //把相机坐标设置成可观察对象
const { x, y, z } = toRefs(map); //输出坐标给模板使用
let scene,
    camera,
    renderer,
    controls;
// directionalLight,
// hemisphereLight; // 定义所有three实例变量
let isLoading = ref(true); //是否显示loading  这个load模型监听的进度
let loadingWidth = ref(0); // loading的进度

let objects = [];

//初始化所有函数
const init = async () => {
    setScene();
    setCamera();
    setLight();
    setControls();
    setObjects();
    loop();
};

// 创建场景
const setScene = () => {
    scene = new THREE.Scene();
    scene.background = new THREE.Color('#d6d8da');
    renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
    });
    renderer.setSize(innerWidth, innerHeight);
    document.querySelector(".boxs").appendChild(renderer.domElement);
};


// 创建相机
const setCamera = () => {
    /**
           * dat
           */
    let guiControls = {
        near: 0.1,
        far: 100,
        fov: 60,
        ax: 0,
        ay: 0,
        az: 20,
        cpx: 0,
        cpy: 1.5,
        cpz: 2
    };

    camera = new THREE.PerspectiveCamera(guiControls.fov, window.innerWidth / window.innerHeight, guiControls.near, guiControls.far);
    camera.position.set(guiControls.cpx, guiControls.cpy, guiControls.cpz);
    camera.lookAt(guiControls.ax, guiControls.ay, guiControls.az);

    const helper = new THREE.CameraHelper(camera);
    scene.add(helper);

    const folder = gui.addFolder('相机设置');
    folder
        .add(guiControls, 'near', 0.01, 20, 0.1)
        .name('相机near:')
        .onChange(e => {
            camera.near = e;
            camera.updateProjectionMatrix();
        });
    folder
        .add(guiControls, 'far', 1, 1000, 1)
        .name('相机far:')
        .onChange(e => {
            camera.far = e;
            camera.updateProjectionMatrix();
        });
    folder
        .add(guiControls, 'fov', 50, 150, 1)
        .name('相机fov:')
        .onChange(e => {
            camera.fov = e;
            camera.updateProjectionMatrix();
        });
    folder
        .add(guiControls, 'ax', -50, 50, 0.1)
        .name('相机lookAt _x:')
        .onChange(e => {
            camera.lookAt(e, guiControls.ay, guiControls.az);
        });
    folder
        .add(guiControls, 'ay', -50, 50, 0.1)
        .name('相机lookAt _y:')
        .onChange(e => {
            camera.lookAt(guiControls.ax, e, guiControls.az);
        });
    folder
        .add(guiControls, 'az', -50, 50, 0.1)
        .name('相机lookAt _z:')
        .onChange(e => {
            camera.lookAt(guiControls.ax, guiControls.ay, e);
        });
    folder
        .add(guiControls, 'ax', -50, 50, 0.1)
        .name('相机position _x:')
        .onChange(e => {
            camera.position.set(e, guiControls.ay, guiControls.az);
        });
    folder
        .add(guiControls, 'ay', -50, 50, 0.1)
        .name('相机position _y:')
        .onChange(e => {
            camera.position.set(guiControls.ax, e, guiControls.az);
        });
    folder
        .add(guiControls, 'az', -50, 50, 0.1)
        .name('相机position _z:')
        .onChange(e => {
            camera.position.set(guiControls.ax, guiControls.ay, e);
        });
};

//创建灯光
const setLight = () => {
    // directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
    // directionalLight.position.set(-4, 8, 4);
    // hemisphereLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.8);
    // hemisphereLight.position.set(0, 8, 0);
    // scene.add(directionalLight);
    // scene.add(hemisphereLight);


    // // 平行光
    // let lightControls3 = {
    //   x: .9,
    //   y: -3.9,
    //   z: 1.8,
    //   intensity: 4
    // };

    // const light3 = new THREE.DirectionalLight(0xFFFFFF, lightControls3.intensity);
    // light3.width = 30;
    // light3.position.set(lightControls3.x, lightControls3.y, lightControls3.z)
    // const helper = new THREE.DirectionalLightHelper(light3, 1);
    // scene.add(light3);
    // scene.add(helper);

    // const targetObject = new THREE.Object3D();
    // scene.add(targetObject);
    // light3.target = targetObject;


    // const folder3 = gui.addFolder('平行光设置');
    // folder3
    //   .add(lightControls3, 'x', -20, 20, .1)
    //   .name('x:')
    //   .onChange(e => {
    //     light3.position.set(e, lightControls3.y, lightControls3.z);
    //   });
    // folder3
    //   .add(lightControls3, 'y', -20, 20, .1)
    //   .name('y:')
    //   .onChange(e => {
    //     light3.position.set(lightControls3.x, e, lightControls3.z);

    //   });
    // folder3
    //   .add(lightControls3, 'z', -20, 20, .1)
    //   .name('z:')
    //   .onChange(e => {
    //     light3.position.set(lightControls3.x, lightControls3.y, e);

    //   });
    // folder3
    //   .add(lightControls3, 'intensity', 0, 10, 0.1)
    //   .name('intensity:')
    //   .onChange(e => {
    //     light3.intensity = e;
    //   });


    // 环境灯
    let lightControls = {
        intensity: 1.5,
        color: new THREE.Color('#a59b92')
    };
    const light = new THREE.AmbientLight(lightControls.color, lightControls.intensity); // soft white light
    // light.position.set()
    scene.add(light);
    const folder = gui.addFolder('环境光设置');
    folder
        .add(lightControls, 'intensity', 0, 10, 0.1)
        .name('intensity:')
        .onChange(e => {
            light.intensity = e;
        });
    folder.addColor(lightControls, "color").onChange((e) => {
        light.color.set(new THREE.Color(e))
    });

    // 半球光
    // const light4 = new THREE.HemisphereLight(0x363636, 0x696969, 50);
    // scene.add(light4);



    // 聚光灯
    let lightControls5 = {
      x: 0,
      y: -20,
      z: 0,
      intensity: 2.9
    };

    const spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(lightControls5.x, lightControls5.y, lightControls5.z);
    spotLight.castShadow = true;
    spotLight.shadow.mapSize.width = 1024;
    spotLight.shadow.mapSize.height = 1024;
    spotLight.shadow.camera.near = 500;
    spotLight.shadow.camera.far = 4000;
    spotLight.shadow.camera.fov = 30;
    const spotLightHelper = new THREE.SpotLightHelper(spotLight);
    scene.add(spotLightHelper);
    scene.add(spotLight);
    const folder5 = gui.addFolder('光照设置');
    folder5
      .add(lightControls5, 'x', -20, 20, .1)
      .name('x:')
      .onChange(e => {
        spotLight.position.set(e, lightControls5.y, lightControls5.z);
      });
    folder5
      .add(lightControls5, 'y', -20, 20, .1)
      .name('y:')
      .onChange(e => {
        spotLight.position.set(lightControls5.x, e, lightControls5.z);

      });
    folder5
      .add(lightControls5, 'z', -20, 20, .1)
      .name('z:')
      .onChange(e => {
        spotLight.position.set(lightControls5.x, lightControls5.y, e);

      });
    folder5
      .add(lightControls5, 'intensity', 0, 5, 0.1)
      .name('intensity:')
      .onChange(e => {
        spotLight.intensity = e;
      });



    // 点光源
    // let lightControls2 = {
    //     x: 0,
    //     y: -93,
    //     z: 7,
    //     intensity: 3
    // };

    // const pointLight = new THREE.PointLight(0xffffff, lightControls2.intensity);
    // pointLight.position.set(lightControls2.x, lightControls2.y, lightControls2.z);
    // scene.add(pointLight);
    // const sphereSize = 1;
    // const pointLightHelper = new THREE.PointLightHelper(pointLight, sphereSize);
    // scene.add(pointLightHelper);

    // const folder2 = gui.addFolder('点光源光照设置');
    // folder2
    //     .add(lightControls2, 'x', -100, 100, 1)
    //     .name('x:')
    //     .onChange(e => {
    //         pointLight.position.set(e, lightControls2.y, lightControls2.z);
    //     });
    // folder2
    //     .add(lightControls2, 'y', -100, 100, 1)
    //     .name('y:')
    //     .onChange(e => {
    //         pointLight.position.set(lightControls2.x, e, lightControls2.z);

    //     });
    // folder2
    //     .add(lightControls2, 'z', -100, 100, 1)
    //     .name('z:')
    //     .onChange(e => {
    //         pointLight.position.set(lightControls2.x, lightControls2.y, e);

    //     });
    // folder2
    //     .add(lightControls2, 'intensity', 0, 5, 0.1)
    //     .name('intensity:')
    //     .onChange(e => {
    //         pointLight.intensity = e;
    //     });
};

// 设置模型控制
const setControls = () => {
    controls = new OrbitControls(camera, renderer.domElement);
    // controls.maxPolarAngle = (0.9 * Math.PI) / 2;
    controls.enableZoom = true;
    controls.addEventListener("change", render);
};

// 加载or创建模型
const setObjects = async () => {
    isLoading.value = false;
    const textureLoader = new THREE.TextureLoader();
    /**
     *  homeObj
     */
    const homeObj = new THREE.Object3D();
    homeObj.name = 'homeObj';
    homeObj.position.set(0, 0, 0);
    // axesHelper
    const axesHelper = new THREE.AxesHelper(10);
    homeObj.add(axesHelper);
    // gridHelper
    const size = 5;
    const divisions = 5;
    const gridHelper = new THREE.GridHelper(size, divisions);
    homeObj.add(gridHelper);
    scene.add(homeObj);
    objects.push(homeObj);
    /**
     * 物体Obj
     */
    // const workObj = new THREE.Object3D();
    // workObj.name = "物体";
    // const geometry = new THREE.BoxGeometry(1, 1, 1);
    // const material = new THREE.MeshPhongMaterial({
    //     // color: 0xff0000,
    //     map: textureLoader.load('/static/3d/test/te1.jpg')
    // });
    // const cube = new THREE.Mesh(geometry, material);
    // cube.rotation.x = 3.15;
    // workObj.add(cube);
    // homeObj.add(workObj);
    // objects.push(workObj);

    /**
     * 加载3d模型
     */
    // const work3dObj = new THREE.Object3D();
    // work3dObj.name = "3d模型";
    // const material3d = new THREE.MeshPhongMaterial({
    //     color: 0xff0000,
    //     name: '测试',
    //     map: textureLoader.load('/static/3d/qingtong/4e0703ee-930f-4dee-b053-0280ce7940f7-222.png'),
    // });
    // loader.load('/static/3d/qingtong/1.obj', obj => {
    //     obj.traverse(function (child) {
    //         if (child.isMesh) child.material.map = material3d;
    //     });
    //     obj.scale.set(.05,.05,.05)
    //     // console.log(obj);
    //     work3dObj.add(obj);
    //     homeObj.add(work3dObj);
    //     objects.push(work3dObj);
    // });
    // function loadObjFile() {
    //     return new Promise(resolve => {
    //         loader.load('/static/3d/wan/2.obj', obj => {
    //             resolve(obj);
    //         });
    //     })
    // }
    // const cube3d = await loadObjFile();
    // cube3d.traverse(child => {
    //     if (child.isMesh) child.material.map =  textureLoader.load('/static/3d/test/te1.jpg');
    // })
    // cube3d.children.forEach(item => {
    //     if (item.type == "Mesh") {
    //         //设置模型皮肤
    //         item.material.map = material3d;
    //     }
    // })
    // console.log(cube3d);
    // work3dObj.add(cube3d);
    // homeObj.add(work3dObj);
    // objects.push(work3dObj);
}

// 循环场景 、相机、 位置更新
const loop = () => {
    requestAnimationFrame(loop);
    renderer.render(scene, camera);
    controls.update();
};


//返回坐标信息
const render = () => {
    map.x = Number.parseInt(camera.position.x);
    map.y = Number.parseInt(camera.position.y);
    map.z = Number.parseInt(camera.position.z);
};


//是否自动转动
const isAutoFun = () => {
    controls.autoRotate = true;
};
//停止转动
const stop = () => {
    controls.autoRotate = false;
};


//用vue钩子函数调用
onMounted(init);
</script>

<style>
body {
    margin: 0;
    padding: 0;
}

.maskLoading {
    background: rgb(220, 220, 220);
    position: fixed;
    display: flex;
    justify-content: center;
    align-items: center;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1111111;
    color: #fff;
}

.maskLoading .loading {
    width: 400px;
    height: 20px;
    border: 1px solid #fff;
    background: #000;
    overflow: hidden;
    border-radius: 10px;
}

.maskLoading .loading div {
    background: #fff;
    height: 20px;
    width: 0;
    transition-duration: 500ms;
    transition-timing-function: ease-in;
}

canvas {
    width: 100%;
    height: 100%;
    margin: 0;
    position: fixed;
    top: 0;
    left: 0;
}

.mask {
    color: #fff;
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
}

.flex {
    display: flex;
    flex-wrap: wrap;
    padding: 20px;
}

.flex div {
    width: 10px;
    height: 10px;
    margin: 5px;
    cursor: pointer;
}
</style>

